#include "FKServerObjectManager.h"
#include <QVariant>
#include <QTcpServer>
#include <QTcpSocket>

#include "FKLogger.h"

#include "FKEvent.h"
#include "FKClient.h"
#include "FKClientManager.h"
#include "FKFileSender.h"
#include "FKPacker.h"
//#include "FKClientData.h"

FKServerObjectManager::FKServerObjectManager():FKAbstractObjectManager(){
    FK_CBEGIN
    _server=new QTcpServer;
    connect(_server,SIGNAL(newConnection()),SLOT(newConnection()));
    FK_CEND
}

FKServerObjectManager::~FKServerObjectManager(){
    FK_DBEGIN
    _server->deleteLater();
    FK_DEND
}

bool FKServerObjectManager::startServer(int port){
    return _server->listen(QHostAddress::Any,port);
}

void FKServerObjectManager::newConnection(){
    FKClientManager* manager=new FKClientManager(_server->nextPendingConnection(),this);
    connect(manager,SIGNAL(message(QString,FKClientManager*)),manager,SLOT(sendMessage(QString)));
    connect(manager,SIGNAL(genClientRequested(QString,QString,QVariant,FKClientManager*)),SLOT(genClient(QString,QString,QVariant,FKClientManager*)));
    connect(manager,SIGNAL(clientRequested(QString,QString,FKClientManager*)),SLOT(getClient(QString,QString,FKClientManager*)));
    connect(manager,SIGNAL(disconnected(FKClientManager*)),SLOT(resetManager(FKClientManager*)));
    manager->startDeletingTimer();
}

void FKServerObjectManager::internalEvent(FKEvent* event){
    QList<FKClientManager*> clients;
    FKClientManager* manager;
    foreach(qint32 clientID, event->recievers()){
        manager=_clients.value(clientID,0);
        if(manager)clients.append(manager);
    }
    if(!clients.isEmpty()){
        QByteArray message(FKClientManager::preserveData(FKPacker::pack(FKPacker::event, event)));
        foreach(FKClientManager* client,clients)client->sendData(message);
    }
    if(event->recievers().contains(-1)){
        if(getLocalClient()){
            getLocalClient()->manageEvent(event);
        }else{
            returnMessage(event->client(), QString("No client for internal event"));
            event->deleteLater();
        }
    }else if(event->recievers().contains(-2)){
        if(getLocalClient() && event->recievers().contains(getLocalClient()->getID())){
            getLocalClient()->manageEvent(event);
        }else{
//            returnMessage(event->client(), QString("No client for internal event"));
            event->deleteLater();
        }
    }else{
        event->deleteLater();
    }
}

void FKServerObjectManager::returnMessage(qint32 clientID, QString text){
    if(_clients.contains(clientID)){
        sendMessage(text,_clients.value(clientID));
    }else{
        showMessage(text+QString(". Owner: ")+QString::number(clientID));
    }
}

void FKServerObjectManager::sendMessage(QString message, FKClientManager *manager){
    manager->sendMessage(message);
}

//void FKServerObjectManager::clientRequested(QString clientName, QString password){
//    getClient(clientName,password,0);
//}

void FKServerObjectManager::getClient(QString clientName, QString password, FKClientManager *s){
    if(!s){
        QString error(checkClient(clientName,password));
        if(error==QString()){
            FKClient* client=catchClient(clientName,password);
            if(_clients.value(client->getID(),0) || getLocalClient()==client){
                showMessage(QString("client already in use"));
            }else{
                setLocalClient(client);
            }
        }else{
            showMessage(error);
        }
    }else{
        if(!s->client()){
            QString error(checkClient(clientName,password));
            if(error==QString()){
                FKClient* client=catchClient(clientName,password);
                if(_clients.value(client->getID(),0) || getLocalClient()==client){
                    sendMessage(QString("client already in use"),s);
                }else{
                    s->stopDeletingTimer();
                    connect(s,SIGNAL(gotAction(FKEvent*)),SLOT(action(FKEvent*)));
                    _managers[s]=client->getID();
                    _clients[client->getID()]=s;
        //            FKClientData data;
                    QByteArray data(s->preserveData(FKPacker::pack(FKPacker::client,client)));
                    s->sendData(data);
                    FKFileSender* fs=new FKFileSender(s);
                    connect(fs,SIGNAL(reply(QVariant)),s,SLOT(sendFileMessage(QVariant)));
                    connect(s,SIGNAL(fileMessage(QVariant)),fs,SLOT(getNextBlock(QVariant)));
                    connect(s,SIGNAL(interruptFileMessage(QString)),fs,SLOT(interruptUploading(QString)));
                    s->setClient(client);
                    client->reconnect();
                }
            }else{
                sendMessage(error,s);
            }
        }else{
            sendMessage(QString("client already created"),s);
        }
    }
}

void FKServerObjectManager::resetManager(FKClientManager *m){
    _clients.remove(_managers.take(m));
    m->deleteLater();
}
